# coding:utf-8

import time
import math

import wx.lib.rcsizer as rcs
import matplotlib
import matplotlib.figure
import matplotlib.backends.backend_wxagg
import matplotlib.backends.backend_wx
from mpl_toolkits.axes_grid1.axes_divider import make_axes_area_auto_adjustable

import Global

try:
    from agw import fourwaysplitter as FWS
except ImportError:  # if it's not there locally, try the wxPython lib.
    try:
        import wx.lib.agw.fourwaysplitter as FWS
    except ImportError:
        exit()

# 菜单ID
from AppIds import *

import wx.lib.newevent

# Frame start
SERIAL_GENIUS_FS_CHAR = 0x0F
# Slash
SERIAL_GENIUS_SL_CHAR = 0x1F

ANGLE_EMPTY = -999999
DEBUG = False


# Rehoo金属探测
class Rehoodetector(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, style=wx.BORDER_DOUBLE)

        ############# 状态信息 ############
        # 该模块是否启用
        self.isUsing = False
        self.changed = False
        self.autoScale = True

        ############# 配置信息 ############
        self.dataBuffer = []

        self.refreshTimer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.PlotData)
        self.refreshTimer.Start(500)

        ############# 开始布局 ###########
        gridSizer = rcs.RowColSizer()
        rowTotal = 4
        colTotal = 6

        # 标题
        title = wx.StaticText(self, -1, u"金属探测")
        title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
        gridSizer.Add(title, pos=(0, 0), size=(1, colTotal), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)

        # 绘图区
        self.figure = matplotlib.figure.Figure(figsize=(1, 1))
        self.figure.subplots_adjust(left=0.00, bottom=0.00, right=1.00, top=1.00, wspace=None, hspace=None)
        self.axes = self.figure.add_subplot(111)
        self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg(self, 20, self.figure)
        gridSizer.Add(self.canvas, pos=(1, 0), size=(1, colTotal), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
        make_axes_area_auto_adjustable(self.axes)
        self.canvas.mpl_connect('button_press_event', self.on_button_press_event)

        # 清空
        btn = wx.Button(self, -1, u"清空")
        self.Bind(wx.EVT_BUTTON, self.OnClearData, btn)
        gridSizer.Add(btn, pos=(2, 0), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        btn = wx.Button(self, -1, u"更新")
        self.Bind(wx.EVT_BUTTON, self.OnUpdateData, btn)
        gridSizer.Add(btn, pos=(2, 1), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        btn = wx.Button(self, -1, u"测试")
        self.Bind(wx.EVT_BUTTON, self.OnTestData, btn)
        gridSizer.Add(btn, pos=(2, 2), size=(1, 1), flag=wx.ALIGN_CENTER_VERTICAL)

        # 工具条
        self.toolbar = matplotlib.backends.backend_wx.NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        gridSizer.Add(self.toolbar, pos=(2, 3), size=(1, colTotal - 3), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)

        # Global.SerialGeniusPort.SendAppend(self.dataBuffer)

        # 设置变宽信息
        gridSizer.AddGrowableCol(colTotal - 1)
        gridSizer.AddGrowableRow(1)

        ############# 结束布局 ###########
        self.SetSizer(gridSizer)
        self.SetAutoLayout(True)

        ############# 结束布局 ###########

        self.dataAxes_H, = self.axes.plot([], [], color='blue', linestyle='-', marker='.', markerfacecolor='blue',
                                          markersize=2)
        self.dataAxes_L, = self.axes.plot([], [], color='red', linestyle='-', marker='.', markerfacecolor='red',
                                          markersize=2)
        self.dataAxes_Line_H, = self.axes.plot([], [], color='blue', linestyle='-', linewidth=3.0, marker='.',
                                               markerfacecolor='red', markersize=0)
        self.dataAxes_Line_L, = self.axes.plot([], [], color='red', linestyle='-', linewidth=3.0, marker='.',
                                               markerfacecolor='red', markersize=0)
        self.axes.grid(True)

        self.datax_H = []
        self.datay_H = []
        self.datax_L = []
        self.datay_L = []
        self.data_angle_H = ANGLE_EMPTY
        self.data_angle_L = ANGLE_EMPTY

        '''
        import struct
        import random
        f = open('rehoodetectordata.bin', 'wb')
        f.write('\xAA')
        f.write('\xAA')
        f.write('\xAA')
        f.write('\xAA')
        f.write('\x04')
        f.write('\x00')
        for i in range(1024*8):
            f.write(struct.pack('B',random.randint(10,99)))
        f.close()
        '''

    # 新增串口数据，被串口接收所调用
    # AA AA AA AA
    # Angle_H Angle_H
    # DataLen_H DataLen_L
    # Data...
    def RecvData(self, data):
        self.dataBuffer.extend(data)
        if len(self.dataBuffer) < 10:
            return

        if (self.dataBuffer[0] == 0xAA and
                    self.dataBuffer[1] == 0xAA and
                    self.dataBuffer[2] == 0xAA and
                    self.dataBuffer[3] == 0xAA):

            # 角度 高频
            valueH = self.dataBuffer[4]
            valueL = self.dataBuffer[5]
            self.data_angle_H = (valueH << 8) | valueL

            # 角度 低频
            valueH = self.dataBuffer[6]
            valueL = self.dataBuffer[7]
            self.data_angle_L = (valueH << 8) | valueL

            # 数据长度
            valueH = self.dataBuffer[8]
            valueL = self.dataBuffer[9]
            dataLen = (valueH << 8) | valueL
            # 最大长度判断
            if dataLen > 10240:
                self.dataBuffer = []
                return

            if len(self.dataBuffer) < 10 + dataLen * 8:
                return
            if DEBUG:
                print("Data full " + str(dataLen))

            for i in range(0, 10):
                self.dataBuffer.pop(0)

            self.datax_H = []
            self.datay_H = []
            self.datax_L = []
            self.datay_L = []

            index = 6
            for i in range(dataLen):
                for types in range(4):
                    valueH = self.dataBuffer.pop(0)
                    valueL = self.dataBuffer.pop(0)
                    value = (valueH << 8) | valueL
                    if value > 0x7FFF:
                        value = value - 0x10000

                    if types == 0:
                        self.datax_H.append(value)
                    elif types == 1:
                        self.datay_H.append(value)
                    elif types == 2:
                        self.datax_L.append(value)
                    elif types == 3:
                        self.datay_L.append(value)

            self.changed = True
        else:
            while len(self.dataBuffer) > 4 and (self.dataBuffer[0] != 0xAA or
                                                        self.dataBuffer[1] != 0xAA or
                                                        self.dataBuffer[2] != 0xAA or
                                                        self.dataBuffer[3] != 0xAA):
                self.dataBuffer.pop(0)

    # 清空数据
    def OnClearData(self, event):
        self.datax_H = []
        self.datay_H = []
        self.datax_L = []
        self.datay_L = []
        self.data_angle_H = ANGLE_EMPTY
        self.data_angle_L = ANGLE_EMPTY
        self.changed = True

    # 重绘函数
    def OnPaint(self, event):
        self.canvas.draw()

    def PlotData(self, evt=None):
        if DEBUG:
            print(time.strftime('timer_%Y%m%d_%H_%M_%S', time.localtime(time.time())))

        if not self.changed:
            return

        self.changed = False

        self.dataAxes_H.set_data(self.datax_H, self.datay_H)
        self.dataAxes_L.set_data(self.datax_L, self.datay_L)

        legend = [u'High', u'Low']

        if self.data_angle_H == ANGLE_EMPTY:
            self.dataAxes_Line_H.set_data([], [])
        else:
            angle = self.data_angle_H * math.pi / 180.0
            self.dataAxes_Line_H.set_data([-10000 * math.cos(angle), 10000 * math.cos(angle)],
                                          [-10000 * math.sin(angle), 10000 * math.sin(angle)])
            legend.append(str(self.data_angle_H) + u' °')

        if self.data_angle_L == ANGLE_EMPTY:
            self.dataAxes_Line_L.set_data([], [])
        else:
            angle = self.data_angle_L * math.pi / 180.0
            self.dataAxes_Line_L.set_data([-10000 * math.cos(angle), 10000 * math.cos(angle)],
                                          [-10000 * math.sin(angle), 10000 * math.sin(angle)])
            legend.append(str(self.data_angle_L) + u' °')

        self.axes.legend(legend)

        if DEBUG:
            print(time.strftime('update_%Y%m%d_%H_%M_%S', time.localtime(time.time())))

        if self.autoScale:
            if len(self.datax_H) > 0 and len(self.datay_H) and len(self.datax_L) > 0 and len(self.datay_L) > 0:

                minv = min(min(self.datax_H), min(self.datax_L))
                maxv = max(max(self.datax_H), max(self.datax_L))
                if minv or maxv:
                    if minv == maxv:
                        maxv = minv + 1
                    if minv < -7000:
                        minv = -9000
                    if maxv > 7000:
                        maxv = 9000
                else:
                    minv = -9000
                    maxv = 9000
                self.axes.set_xlim(minv, maxv)

                minv = min(min(self.datay_H), min(self.datay_L))
                maxv = max(max(self.datay_H), max(self.datay_L))
                if minv or maxv:
                    if minv == maxv:
                        maxv = minv + 1
                    if minv < -7000:
                        minv = -9000
                    if maxv > 7000:
                        maxv = 9000
                else:
                    minv = -9000
                    maxv = 9000
                self.axes.set_ylim(minv, maxv)
            else:
                self.axes.set_xlim(-9000, +9000)
                self.axes.set_ylim(-9000, +9000)

        try:
            self.canvas.draw()
        except:
            pass

    def OnUpdateData(self, event):
        if Global.SerialGeniusPort and Global.SerialGeniusPort.running:
            data = []
            sendStr = 'DISP EAD\r\n'
            for i in range(0, len(sendStr)):
                data.append(ord(sendStr[i]))
            Global.SerialGeniusPort.SendAppend(data)
        else:
            wx.MessageBox(u'请先打开串口', u'提示')

    def OnTestData(self, event):
        if Global.SerialGeniusPort and Global.SerialGeniusPort.running:
            # send string
            data = []
            sendStr = 'string to send'
            for i in range(0, len(sendStr)):
                data.append(ord(sendStr[i]))
            Global.SerialGeniusPort.SendAppend(data)

            '''
            # send list
            data=[]
            data.append(0xAA) 
            data.append(0xAA) 
            data.append(0xAA) 
            data.append(0xAA)
            
            data.append(0x00)
            data.append(0x20)
            data.append(0x00)
            data.append(0x40)
            
            data.append(0x04)
            data.append(0x00)
            
            import random
            for i in range(1024*8):
                data.append(random.randint(0,99))
            
            Global.SerialGeniusPort.SendAppend(data)
            '''
        else:
            wx.MessageBox(u'请先打开串口', u'提示')

    def on_button_press_event(self, event):
        if 'PAN' == self.axes.get_navigate_mode() or 'ZOOM' == self.axes.get_navigate_mode():
            self.autoScale = False
        else:
            self.autoScale = True
